﻿/*
 * 作者：新生命开发团队（http://www.newlifex.com/）
 * 
 * 版权：版权所有 (C) 新生命开发团队 2002-2014
 * 
 * 修改：海洋饼干（cuteant@outlook.com）
*/

using System;
using System.Net;

namespace CuteAnt.Serialization
{
	/// <summary>文本写入器基类</summary>
	/// <typeparam name="TSettings">设置类</typeparam>
	public abstract class TextWriterBase<TSettings> : WriterBase<TSettings> where TSettings : TextReaderWriterSetting, new()
	{
		#region 属性

		/// <summary>是否使用大小，如果使用，将在写入数组、集合和字符串前预先写入大小。字符串类型读写器一般带有边界，不需要使用大小</summary>
		protected override Boolean UseSize { get { return false; } }

		#endregion

		#region 基础元数据

		#region 字节

		/// <summary>将一个无符号字节写入</summary>
		/// <param name="value">要写入的无符号字节。</param>
		public override void Write(Byte value)
		{
			WriteLiteral(String.Format("{0}", value));
		}

		//public override void Write(Byte value) { Write(new Byte[] { value }, 0, 1); }

		/// <summary>将字节数组以[0xff,0xff,0xff]的格式写入</summary>
		/// <param name="buffer">缓冲区</param>
		public override void Write(byte[] buffer)
		{
			if (buffer == null)
				WriteNull();
			else
				Write(buffer, 0, buffer.Length);
		}

		/// <summary>将字节数组部分写入当前流。</summary>
		/// <param name="buffer">包含要写入的数据的字节数组。</param>
		/// <param name="index">buffer 中开始写入的起始点。</param>
		/// <param name="count">要写入的字节数。</param>
		public override void Write(byte[] buffer, int index, int count)
		{
			if (buffer == null || buffer.Length < 1 || count <= 0 || index >= buffer.Length) return;

			if (Settings.UseBase64)
				WriteLiteral(Convert.ToBase64String(buffer, index, count));
			else
				WriteLiteral(BitConverter.ToString(buffer, index, count).Replace("-", null));

			AutoFlush();
		}

		/// <summary>将一个有符号字节写入当前流，并将流的位置提升 1 个字节。</summary>
		/// <param name="value">要写入的有符号字节。</param>
		//[CLSCompliant(false)]
		public override void Write(sbyte value)
		{
			WriteLiteral(String.Format("{0}", value));
		}

		#endregion

		#region 有符号整数

		/// <summary>将 2 字节有符号整数写入当前流，并将流的位置提升 2 个字节。</summary>
		/// <param name="value">要写入的 2 字节有符号整数。</param>
		public override void Write(Int16 value)
		{
			Write((Int32)value);
		}

		/// <summary>将 4 字节有符号整数写入当前流，并将流的位置提升 4 个字节。</summary>
		/// <param name="value">要写入的 4 字节有符号整数。</param>
		public override void Write(Int32 value)
		{
			Write((Int64)value);
		}

		/// <summary>将 8 字节有符号整数写入当前流，并将流的位置提升 8 个字节。</summary>
		/// <param name="value">要写入的 8 字节有符号整数。</param>
		public override void Write(Int64 value)
		{
			WriteLiteral(value.ToString());
		}

		#endregion

		#region 无符号整数

		/// <summary>将 2 字节无符号整数写入当前流，并将流的位置提升 2 个字节。</summary>
		/// <param name="value">要写入的 2 字节无符号整数。</param>
		//[CLSCompliant(false)]
		public override void Write(UInt16 value)
		{
			Write((UInt32)value);
		}

		/// <summary>将 4 字节无符号整数写入当前流，并将流的位置提升 4 个字节。</summary>
		/// <param name="value">要写入的 4 字节无符号整数。</param>
		//[CLSCompliant(false)]
		public override void Write(UInt32 value)
		{
			Write((UInt64)value);
		}

		/// <summary>将 8 字节无符号整数写入当前流，并将流的位置提升 8 个字节。</summary>
		/// <param name="value">要写入的 8 字节无符号整数。</param>
		//[CLSCompliant(false)]
		public override void Write(UInt64 value)
		{
			WriteLiteral(value.ToString());
		}

		#endregion

		#region 浮点数

		/// <summary>将 4 字节浮点值写入当前流，并将流的位置提升 4 个字节。</summary>
		/// <param name="value">要写入的 4 字节浮点值。</param>
		public override void Write(float value)
		{
			WriteLiteral(value.ToString());
		}

		/// <summary>将 8 字节浮点值写入当前流，并将流的位置提升 8 个字节。</summary>
		/// <param name="value">要写入的 8 字节浮点值。</param>
		public override void Write(double value)
		{
			WriteLiteral(value.ToString());
		}

		#endregion

		#region 字符串

		/// <summary>将字符数组部分写入当前流，并根据所使用的 Encoding（可能还根据向流中写入的特定字符），提升流的当前位置。</summary>
		/// <param name="chars">包含要写入的数据的字符数组。</param>
		/// <param name="index">chars 中开始写入的起始点。</param>
		/// <param name="count">要写入的字符数。</param>
		public override void Write(char[] chars, int index, int count)
		{
			if (chars == null || chars.Length < 1 || count <= 0 || index >= chars.Length) return;

			Write(new String(chars, index, count));
		}

		/// <summary>写入字符串</summary>
		/// <param name="value">要写入的值。</param>
		public override void Write(String value)
		{
			WriteLiteral(value);
		}

		/// <summary>输出字符串字面值,不做编码处理</summary>
		/// <param name="value">数值</param>
		protected void WriteLiteral(String value)
		{
			Depth++;
			WriteLog("WriteLiteral", value);
			OnWriteLiteral(value);
			Depth--;
		}

		/// <summary>输出字符串字面值,不做编码处理</summary>
		/// <param name="value">数值</param>
		protected virtual void OnWriteLiteral(String value)
		{
			throw new NotImplementedException();
		}

		/// <summary>输出空</summary>
		protected virtual void WriteNull()
		{
		}

		#endregion

		#region 其它

		/// <summary>将单字节 Boolean 值写入</summary>
		/// <param name="value">要写入的 Boolean 值</param>
		public override void Write(Boolean value)
		{
			WriteLiteral(value ? "true" : "false");
		}

		/// <summary>将一个十进制值写入当前流，并将流位置提升十六个字节。</summary>
		/// <param name="value">要写入的十进制值。</param>
		public override void Write(decimal value)
		{
			WriteLiteral(value.ToString());
		}

		///// <summary>将一个时间日期写入</summary>
		///// <param name="value">数值</param>
		//public override void Write(DateTime value) { WriteLiteral(value.ToString("yyyy-MM-dd HH:mm:ss")); }

		#endregion

		#endregion

		#region 基础名值

		/// <summary>写入Guid</summary>
		/// <param name="value">数值</param>
		public override void Write(Guid value)
		{
			Write(value.ToString());
		}

		#endregion

		#region 扩展类型

		/// <summary>写入IPAddress</summary>
		/// <param name="value">数值</param>
		protected override void OnWrite(IPAddress value)
		{
			Write(value.ToString());
		}

		/// <summary>写入IPEndPoint</summary>
		/// <param name="value">数值</param>
		protected override void OnWrite(IPEndPoint value)
		{
			Write(value.ToString());
		}

		#endregion

		#region 写入值类型

		/// <summary>写入值类型，只能识别基础类型，对于不能识别的类型，方法返回false</summary>
		/// <param name="value">要写入的对象</param>
		/// <param name="type">要写入的对象类型</param>
		/// <returns>是否写入成功</returns>
		protected override bool WriteValue(object value, Type type)
		{
			if (type == null)
			{
				if (value == null) return false;
				type = value.GetType();
			}

			if (value != null && Settings.UseEnumName)
			{
				if (type != null && type.IsEnum)
				{
					Write(value.ToString());
					return true;
				}
			}

			return base.WriteValue(value, type);
		}

		#endregion

		#region 扩展

		/// <summary>把数据流转为字符串</summary>
		/// <returns></returns>
		public virtual String ToStr()
		{
			if (!Stream.CanSeek) throw new XSerializationException(null, "数据流不支持移动，无法转字符串！");

			Flush();

			// 保持位置，读取后恢复
			Int64 p = Stream.Position;
			Stream.Position = 0;
			String txt = Stream.ToStr(Settings.Encoding);
			Stream.Position = p;
			return txt;
		}

		#endregion
	}
}